home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Mac OS / MLTE SDK / MLTE_Hands-on / MLTESampleShellFinished / MLTESampleShell.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-09  |  23.7 KB  |  916 lines  |  [TEXT/CWIE]

  1. /* --------------------------------------------------------------
  2.     Apple Worldwide Developer Technical Support
  3.  
  4.     MLTESampleShell.c
  5.  
  6.     You may incorporate this sample code into your applications without
  7.     restriction, though the sample code has been provided "AS IS" and the
  8.     responsibility for its operation is 100% yours.  However, what you are
  9.     not permitted to do is to redistribute the source as "Apple Sample Code"
  10.     after having made changes. If you're going to re-distribute the source,
  11.     we require that you make it clear in the source that the code was
  12.     descended from Apple Sample Code, but that you've made changes.
  13.  
  14.     Copyright © 2000 Apple Computer, Inc., All Rights Reserved
  15.     
  16. ----------------------------------------------------------------- */
  17. #include "MLTESampleShell.h"
  18.  
  19. void main(void)
  20. {    
  21.     Initialize();
  22.     EventLoop();
  23. }
  24.  
  25. void Initialize()
  26. {
  27.     Handle        menuBar;
  28.     OSStatus     status = noErr;
  29.     
  30.     MaxApplZone();
  31.     InitGraf((Ptr) &qd.thePort);
  32.     InitFonts();
  33.     InitWindows();
  34.     InitMenus();
  35.     FlushEvents(everyEvent,0);
  36.     TEInit();
  37.     InitDialogs(NULL);
  38.     InitCursor();
  39.     InstallAppleEventHandlers();
  40.     CheckSystemVersion();
  41.     
  42.     // Step 1 -- Initialize MLTE
  43.     TXNMacOSPreferredFontDescription defaults;
  44.  
  45.     defaults.fontID = kTXNDefaultFontName;
  46.     defaults.pointSize = kTXNDefaultFontSize;
  47.     defaults.fontStyle = kTXNDefaultFontStyle ;
  48.     defaults.encoding = kTXNSystemDefaultEncoding;
  49.     status = TXNInitTextension(&defaults, 1, 0);
  50.     if (status != noErr)
  51.         BigBadError(eNoMLTE);
  52.  
  53.     menuBar = GetNewMBar(rMenuBar);        // read in menubar definition
  54.     if (menuBar == NULL)
  55.         BigBadError(eNoMemory);
  56.     SetMenuBar(menuBar);                // install menus
  57.     DisposeHandle(menuBar);
  58.     AppendResMenu(GetMenuHandle(mApple), 'DRVR');    // add Apple Menu Items
  59.  
  60.     // Step 27 -- Create the TXNFontMenuObject
  61.     status = TXNNewFontMenuObject(GetMenuHandle(mFont), mFont, kStartHierMenuID, &gTXNFontMenuObject);
  62.     if (status != noErr)
  63.         BigBadError(eNoCreateFontMenuObject);
  64.  
  65.     DrawMenuBar();
  66.  
  67.     gInBackground = false;    
  68.     gNumDocuments = 0;
  69.     DoNew();    // create a single empty document
  70. }
  71.  
  72. //    Check for Mac OS 8.5 or later
  73. static void CheckSystemVersion(void) 
  74. {
  75.     OSErr    err;
  76.     long    response;
  77.         
  78.     err = Gestalt(gestaltSystemVersion, &response);
  79.     if (response < 0x00000850)
  80.         BigBadError(eWrongSystem);
  81. }
  82.  
  83. // Get events -- handle them in DoEvent. Call AdjustCursor each time through the loop.
  84. void EventLoop()
  85. {
  86.     RgnHandle    cursorRgn;
  87.     Boolean        gotEvent;
  88.     EventRecord    event;
  89.  
  90.     cursorRgn = NewRgn();    // pass WNE an empty region the 1st time thru
  91.  
  92.     do {
  93.         gotEvent = WaitNextEvent(everyEvent, &event, GetSleep(), cursorRgn);
  94.  
  95.         if (gotEvent)
  96.         {
  97.             // make sure we have the right cursor before handling the event
  98.             AdjustCursor(cursorRgn);
  99.             DoEvent(&event);
  100.         }
  101.         else
  102.         {
  103.             DoIdle();        // perform idle tasks when it’s not our event
  104.             // Step 7 -- give time to TSM.
  105.             TXNTSMCheck(NULL, &event);
  106.         }
  107.     } while (true);            // loop forever... we quit via ExitToShell
  108. }
  109.  
  110. // Determine what kind of event we have, and call the appropriate routines.
  111. void DoEvent(EventRecord *event)
  112. {
  113.     short        part, err;
  114.     WindowPtr    window;
  115.     
  116.     switch (event->what) 
  117.     {
  118.         case nullEvent:
  119.             DoIdle();
  120.             break;
  121.         case mouseDown:
  122.             part = FindWindow(event->where, &window);
  123.             switch (part) 
  124.             {
  125.                 case inMenuBar:             // process a mouse menu command (if any)
  126.                     AdjustMenus();            // bring ’em up-to-date
  127.                     DoMenuCommand(MenuSelect(event->where));
  128.                     break;
  129.                 case inSysWindow:           // let the system handle the mouseDown
  130.                     SystemClick(event, window);
  131.                     break;
  132.                 case inContent:
  133.                     if (window != FrontWindow()) 
  134.                         SelectWindow(window);
  135.                     else
  136.                     {
  137.                         DoContentClick(window, event);
  138.                         AdjustMenus();
  139.                     }
  140.                     break;
  141.                 case inDrag:                // pass screenBits.bounds to get all gDevices
  142.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  143.                     break;
  144.                 case inGoAway:
  145.                     if (TrackGoAway(window, event->where))
  146.                         DoCloseWindow(window); // we don’t care if the user cancelled
  147.                     break;
  148.                 case inGrow:
  149.                     DoGrowWindow(window, event);
  150.                     break;
  151.                 case inZoomIn:
  152.                 case inZoomOut:
  153.                     if (TrackBox(window, event->where, part))
  154.                         DoZoomWindow(window, part);
  155.                     break;
  156.             }
  157.             break;
  158.         case keyDown:
  159.         case autoKey:                       // check for menukey equivalents 
  160.             if (event->modifiers & cmdKey)  // Command key down
  161.             {
  162.                 if (event->what == keyDown) 
  163.                 {
  164.                     AdjustMenus();            // enable/disable/check menu items properly
  165.                     DoMenuCommand(MenuKey(event->message & charCodeMask));
  166.                 }
  167.             } 
  168.             else
  169.                 DoKeyDown(event);
  170.             break;
  171.         case activateEvt:
  172.             DoActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
  173.             break;
  174.         case updateEvt:
  175.             DoUpdate((WindowPtr) event->message);
  176.             break;
  177.         case diskEvt:    // handle disk inserted events to recognize uninitialized floppies.
  178.             if (HiWord(event->message) != noErr) 
  179.             {
  180.                 Point    aPoint;
  181.                 SetPt(&aPoint, kDILeft, kDITop);
  182.                 err = DIBadMount(aPoint, event->message);
  183.             }
  184.             break;
  185.         case kOSEvent:
  186.             // BitAND with 0x0FF to get only low byte
  187.             switch ((event->message >> 24) & 0x0FF) // high byte of message
  188.             {        
  189.                 case mouseMovedMessage:
  190.                     DoIdle();                // mouse-moved is also an idle event 
  191.                     break;
  192.                 case suspendResumeMessage:    // suspend/resume is also an activate/deactivate 
  193.                     gInBackground = (event->message & kResumeMask) == 0;
  194.                     DoActivate(FrontWindow(), !gInBackground);
  195.                     break;
  196.             }
  197.             break;
  198.     }
  199. }
  200.  
  201. //    Change the cursor's shape, depending on its position.
  202. void AdjustCursor(RgnHandle region)
  203. {
  204.     WindowPtr    window = FrontWindow();    // only adjust when we are in front        
  205.     TXNObject     object = NULL;
  206.  
  207.     // Step 8 -- let MLTE adjust the cursor.
  208.     if (IsAppWindow(window))
  209.     {
  210.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  211.         TXNAdjustCursor(object, region);
  212.     }
  213. }
  214.  
  215. // Handle a mouseDown in the grow box of an active window.
  216. void DoGrowWindow(WindowPtr window, EventRecord *event)
  217. {
  218.     TXNObject     object = NULL;
  219.     
  220.     // Step 11 -- let MLTE grow the window.
  221.     if (IsAppWindow(window))
  222.     {
  223.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  224.         TXNGrowWindow(object, event);
  225.     }
  226. }
  227.  
  228. // Handle a mouseClick in the zoom box of an active window.
  229. void DoZoomWindow(WindowPtr window, short part)
  230. {
  231.     TXNObject     object = NULL;
  232.     
  233.     // Step 12 -- let MLTE zoom the window.    
  234.     if (IsAppWindow(window))
  235.     {
  236.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  237.         TXNZoomWindow(object, part);
  238.     }
  239. }
  240.  
  241. // Called when an update event is received for a window.
  242. void DoUpdate(WindowPtr window)
  243. {
  244.     GrafPtr        curPort;
  245.     TXNObject    object = NULL;
  246.     
  247.     GetPort(&curPort);
  248.     SetPort(window);
  249.     
  250.     // Step 14 -- let MLTE update the window.
  251.     if (IsAppWindow(window))
  252.     {
  253.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  254.         TXNUpdate(object);    // TXNUpdate also calls BeginUpdate() and EndUpdate()
  255.     }
  256.     SetPort(curPort);
  257. }
  258.  
  259. //    Called when a window is activated or deactivated
  260. void DoActivate(WindowPtr window, Boolean  becomingActive)
  261. {
  262.     TXNObject    object     = NULL;
  263.     TXNFrameID     frameID    = 0;
  264.  
  265.     // Step 15 -- let MLTE Activate and Focus the TNXObject.
  266.     if (IsAppWindow(window))
  267.     {
  268.         GetWindowProperty(window, 'GRIT', 'tFrm', sizeof(TXNFrameID), NULL, &frameID);
  269.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  270.  
  271.         if (becomingActive) 
  272.         {
  273.             TXNActivate(object, frameID, becomingActive);
  274.             AdjustMenus();
  275.         } 
  276.         else 
  277.             TXNActivate(object, frameID, becomingActive);
  278.     }
  279.     TXNFocus(object, becomingActive);
  280. }
  281.  
  282. //    Called when a mouseDown occurs in the content of a window
  283. void DoContentClick(WindowPtr window, EventRecord *event)
  284. {
  285.     TXNObject    object = NULL;
  286.     
  287.     // Step 10 -- let MLTE handle the mouse down.
  288.     if (IsAppWindow(window))
  289.     {
  290.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  291.         TXNClick(object, event);
  292.     }
  293. }
  294.  
  295. // Called for any keyDown or autoKey events, except when the Command key is held down.
  296. void DoKeyDown(EventRecord *event)
  297. {
  298.     WindowPtr    window = FrontWindow();
  299.     TXNObject    object = NULL;
  300.  
  301.     // Step 13 -- let MLTE handle the key down
  302.     if (IsAppWindow(window))
  303.     {
  304.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  305.         TXNKeyDown(object, event);
  306.     }
  307. }
  308.  
  309. //    Calculate sleep value for WaitNextEvent.
  310. static UInt32 GetSleep()
  311. {
  312.     UInt32        sleep;
  313.     WindowPtr    window;
  314.     TXNObject     object = NULL;
  315.     
  316.     window = FrontWindow();
  317.     
  318.     // Step 6 -- let MLTE calc the appropriate sleep time.
  319.     if (IsAppWindow(window))
  320.     {
  321.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  322.         sleep = TXNGetSleepTicks(object);     // get appropriate sleep time
  323.     }
  324.     else
  325.         sleep = GetCaretTime();                // use some other value
  326.  
  327.     return sleep;
  328. }
  329.  
  330. // Called when we get a null event.
  331. void DoIdle()
  332. {
  333.     WindowPtr    window = FrontWindow();
  334.     TXNObject    object = NULL;
  335.     
  336.     // Step 9 -- let MLTE handle idle time.
  337.     if (IsAppWindow(window))
  338.     {
  339.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  340.         TXNIdle(object);
  341.     }
  342. }
  343.  
  344. //    Enable and disable menus based on the current state.
  345. void AdjustMenus()
  346. {
  347.     WindowPtr    window;
  348.     TXNObject     object = NULL;
  349.     MenuHandle    menu;
  350.     Boolean        undo, redo, cutCopyClear, paste, selectAll;
  351.     
  352.     window = FrontWindow();
  353.  
  354.     menu = GetMenuHandle(mFile);
  355.     if (gNumDocuments < kMaxOpenDocuments)
  356.         EnableItem(menu, iNew);        // New is enabled when we can open more documents
  357.     else
  358.         DisableItem(menu, iNew);
  359.         
  360.     if (window != NULL)                // Printing and Close are enabled when a window is up
  361.     {
  362.         EnableItem(menu, iPageSetup);
  363.         EnableItem(menu, iPrint);    
  364.         EnableItem(menu, iClose);
  365.     }
  366.     else
  367.     {
  368.         DisableItem(menu, iPageSetup);
  369.         DisableItem(menu, iPrint);    
  370.         DisableItem(menu, iClose);
  371.     }
  372.     
  373.     menu = GetMenuHandle(mEdit);
  374.     undo = redo = cutCopyClear = paste = selectAll = false;
  375.     
  376.     if (IsDAWindow(window))
  377.         undo = redo = cutCopyClear = paste = selectAll = true;
  378.     else if (IsAppWindow(window)) 
  379.     {
  380.         // Step 16 -- decide if Undo and Redo should be enabled.
  381.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  382.         if (TXNCanUndo(object, NULL))
  383.             undo = true;
  384.         if (TXNCanRedo(object, NULL))
  385.             redo = true;
  386.         // Step 19 -- decide if Cut, Copy, Clear should be enabled.
  387.         if (!TXNIsSelectionEmpty(object))
  388.             cutCopyClear = true;
  389.         // Step 23 -- decide if Paste should be enabled.
  390.         if (TXNIsScrapPastable())
  391.             paste = true;
  392.         // Step 25 -- decide if Select All should be enabled.
  393.         if (TXNDataSize(object))
  394.             selectAll = true;
  395.     }
  396.     
  397.     if (undo)
  398.         EnableItem(menu, iUndo);
  399.     else
  400.         DisableItem(menu, iUndo);
  401.  
  402.     if (redo)
  403.         EnableItem(menu, iRedo);
  404.     else
  405.         DisableItem(menu, iRedo);
  406.         
  407.     if (cutCopyClear) 
  408.     {
  409.         EnableItem(menu, iCut);
  410.         EnableItem(menu, iCopy);
  411.         EnableItem(menu, iClear);
  412.     } 
  413.     else 
  414.     {
  415.         DisableItem(menu, iCut);
  416.         DisableItem(menu, iCopy);
  417.         DisableItem(menu, iClear);
  418.     }
  419.     
  420.     if (paste)
  421.         EnableItem(menu, iPaste);
  422.     else
  423.         DisableItem(menu, iPaste);
  424.         
  425.     if (selectAll)
  426.         EnableItem(menu, iSelectAll);
  427.     else
  428.         DisableItem(menu, iSelectAll);
  429.  
  430.     InvalMenuBar();        // invalidate menubar - will update next event loop
  431. }
  432.  
  433. //    Handles items chosen from the menu bar.
  434. void DoMenuCommand(long menuResult)
  435. {
  436.     WindowPtr        window;
  437.     TXNObject        object = NULL;
  438.     short            menuID, menuItem;
  439.     short            itemHit, daRefNum;
  440.     Str255            daName;
  441.     OSStatus        status = noErr;
  442.  
  443.     window = FrontWindow();
  444.     menuID = HiWord(menuResult);    // use macros to get menu 
  445.     menuItem = LoWord(menuResult);    // item number and menu number
  446.  
  447.     switch (menuID) 
  448.     {
  449.         case mApple:
  450.             switch (menuItem) 
  451.             {
  452.                 case iAbout:        // bring up alert for About
  453.                     itemHit = Alert(rAboutAlert, NULL);
  454.                                         
  455.                 default:            // non-About items are DAs et al
  456.                     MenuHandle appleMenuHandle = GetMenuHandle(mApple);
  457.                     if (appleMenuHandle != NULL)
  458.                         GetMenuItemText(appleMenuHandle, menuItem, daName);
  459.                     daRefNum = OpenDeskAcc(daName);
  460.                     break;
  461.             }
  462.             break;
  463.         case mFile:
  464.             switch (menuItem) 
  465.             {
  466.                 case iNew:
  467.                     DoNew();
  468.                     break;
  469.                 case iClose:
  470.                     DoCloseWindow(FrontWindow());    // ignore the result
  471.                     break;
  472.                 case iPageSetup:
  473.                     // Step 34 -- let MLTE handle Page Setup.
  474.                     GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  475.                     TXNPageSetup(object);
  476.                     break;
  477.                 case iPrint:
  478.                     // Step 35 -- let MLTE handle Print.
  479.                     GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  480.                     TXNPrint(object);
  481.                     break;
  482.                 case iQuit:
  483.                     Terminate();
  484.                     break;
  485.             }
  486.             break;
  487.         case mEdit:            
  488.             if (IsAppWindow(window))
  489.             {
  490.                 GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  491.                 switch (menuItem) 
  492.                 {
  493.                     case iUndo:
  494.                         // Step 17 -- let MLTE handle Undo.
  495.                         TXNUndo(object);
  496.                         break;
  497.                     case iRedo:
  498.                         // Step 18 -- let MLTE handle Redo.
  499.                         TXNRedo(object);
  500.                         break;
  501.                     case iCut:
  502.                         // Step 20 -- let MLTE handle Cut.
  503.                         TXNCut(object);                    
  504.                         break;
  505.                     case iCopy:
  506.                         // Step 21 -- let MLTE handle Copy.
  507.                         TXNCopy(object);
  508.                         break;
  509.                     case iPaste:
  510.                         // Step 24 -- let MLTE handle Paste.
  511.                         TXNPaste(object);
  512.                         break;
  513.                     case iClear:
  514.                         // Step 22 -- let MLTE handle Clear.
  515.                         TXNClear(object);
  516.                         break;
  517.                     case iSelectAll:
  518.                         // Step 26 -- let MLTE handle Select All.
  519.                         TXNSelectAll(object);
  520.                         break;
  521.                     default:
  522.                         break;
  523.                 }
  524.             }    
  525.         case mFont:
  526.             DoFontMenu(menuID, menuItem, window);
  527.             break;
  528.         case mSize:
  529.             if (IsAppWindow(window))
  530.             {
  531.                 // Step 30 -- let MLTE change selected text to selected size.
  532.                 // The structure containing attributes we would like to set.
  533.                 TXNTypeAttributes    typeAttr;
  534.                 
  535.                 // These are the possible size choices the app offers.
  536.                 static short aFontSizeList[] = {9, 10, 12, 14, 18, 24, 36};
  537.                 
  538.                 // This is the size the user chose, off 1 b/c arrays are zero-based
  539.                 short shortValue = aFontSizeList[menuItem - 1];
  540.                 
  541.                 // Constant specifying size attribute -- FOUR_CHAR_CODE('size')
  542.                 typeAttr.tag = kTXNQDFontSizeAttribute;
  543.                 // Constant specifying the size of the size attribute -- sizeof(SInt16)
  544.                 typeAttr.size = kTXNQDFontSizeAttributeSize;
  545.                 // move data into high byte
  546.                 typeAttr.data.dataValue = shortValue << 16;
  547.                 
  548.                 GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  549.                 // Set the size attributes
  550.                 TXNSetTypeAttributes(object, 1, &typeAttr, kTXNUseCurrentSelection, kTXNUseCurrentSelection);
  551.             }
  552.             break;
  553.         case mStyle:
  554.             if (IsAppWindow(window))
  555.             {
  556.                 TXNTypeAttributes    typeAttr; // struct of attributes we would like to set.
  557.                 Style                newStyle;
  558.                 
  559.                 switch (menuItem) 
  560.                 {
  561.                     case iPlain:
  562.                         newStyle = normal;        // 0        
  563.                         break;
  564.                     case iBold:
  565.                         newStyle = bold;        // 1                
  566.                         break;
  567.                     case iItalic:
  568.                         newStyle = italic;        // 2                
  569.                         break;
  570.                     case iUnderline:
  571.                         newStyle = underline;    // 3                
  572.                         break;
  573.                     case iOutline:
  574.                         newStyle = outline;        // 4                
  575.                         break;
  576.                     case iShadow:
  577.                         newStyle = shadow;        // 0x10                
  578.                         break;
  579.                     case iCondensed:
  580.                         newStyle = condense;    // 0x20                
  581.                         break;                    
  582.                     case iExtended:
  583.                         newStyle = extend;        // 0x40                
  584.                         break;
  585.                     default:
  586.                         break;
  587.                 }
  588.                 // Step 31 -- let MLTE change selected text to selected style.
  589.                 //    Specify the style attributes
  590.                 typeAttr.tag = kTXNQDFontStyleAttribute;
  591.                 typeAttr.size = kTXNQDFontStyleAttributeSize;
  592.                 typeAttr.data.dataValue = newStyle;
  593.                 
  594.                 GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  595.                 //    Set the style attributes
  596.                 TXNSetTypeAttributes(object, 1, &typeAttr, kTXNUseCurrentSelection, kTXNUseCurrentSelection);
  597.             }
  598.             break;
  599.         case mLayout:
  600.             if (menuItem <= iForceJustify)
  601.                 DoJustification(window, menuItem);
  602.             else
  603.                 DoWordWrap(window);
  604.             break;
  605.         default:
  606.             if (menuID >= kStartHierMenuID)
  607.                 DoFontMenu(menuID, menuItem, window);
  608.             break;
  609.     }
  610.     HiliteMenu(0);        // unhighlight the menu
  611.     AdjustMenus();
  612. }
  613.  
  614. // Handle font menu selections
  615. void DoFontMenu(short menuID, short menuItem, WindowPtr window)
  616. {
  617.     TXNObject object = NULL;
  618.     OSStatus  status = noErr;
  619.     
  620.     if (IsAppWindow(window))
  621.     {
  622.         // Step 29 -- let MLTE change selected text to selected font.
  623.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  624.         if (gTXNFontMenuObject != NULL)        
  625.             status = TXNDoFontMenuSelection(object, gTXNFontMenuObject, menuID, menuItem);
  626.         if (status != noErr)
  627.             AlertUser(eNoFontName);
  628.     }
  629. }
  630.  
  631. // Set the justification tag
  632. void DoJustification(WindowPtr window, short menuItem)
  633. {
  634.     TXNObject        object = NULL;
  635.     MenuHandle         layoutMenu;
  636.     OSStatus        status = noErr;
  637.     
  638.     layoutMenu = GetMenuHandle(mLayout);
  639.     
  640.     if (IsAppWindow(window)) 
  641.     {
  642.         SInt32            justification;
  643.         TXNControlTag    controlTag[1];
  644.         TXNControlData    controlData[1];
  645.         
  646.         for (int i = 1; i <= iForceJustify; i++)    // brute technique to uncheck last item
  647.             CheckItem(layoutMenu, i, false);
  648.         
  649.         switch (menuItem) 
  650.         {
  651.             case iDefaultJustify:
  652.                 justification = kTXNFlushDefault;    // flush according to line direction                        
  653.                 break;
  654.             case iLeftJustify:
  655.                 justification = kTXNFlushLeft;
  656.                 break;
  657.             case iRightJustify:
  658.                 justification = kTXNFlushRight;
  659.                 break;
  660.             case iCenterJustify:
  661.                 justification = kTXNCenter;
  662.                 break;
  663.             case iFullJustify:
  664.                 justification = kTXNFullJust;
  665.                 break;
  666.             case iForceJustify:
  667.                 justification = kTXNForceFullJust;    // flush left for all scripts
  668.                 break;
  669.             default:
  670.                 break;
  671.         }
  672.         CheckItem(layoutMenu, menuItem, true);        // check this menu item
  673.         
  674.         // Step 33 -- let MLTE et the document's text justification.
  675.         controlTag[0] = kTXNJustificationTag;
  676.         
  677.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  678.         status = TXNGetTXNObjectControls(object, 1, controlTag, controlData);
  679.         
  680.         if (controlData[0].sValue != justification) // if we have a new justification
  681.         {                     
  682.             controlData[0].sValue = justification;
  683.             status = TXNSetTXNObjectControls(object, false, 1, controlTag, controlData);
  684.         }
  685.     }
  686. }
  687.  
  688. // Toggle word wrap
  689. void DoWordWrap(WindowPtr window)
  690. {
  691.     TXNObject    object = NULL;
  692.     MenuHandle     layoutMenu;
  693.     OSStatus    status = noErr;
  694.     
  695.     layoutMenu = GetMenuHandle(mLayout);
  696.     
  697.     if (IsAppWindow(window))
  698.     {
  699.         TXNControlTag    controlTag[1];
  700.         TXNControlData    controlData[1];
  701.  
  702.         // Step 32 -- let MLTE set the document's word wrap state.
  703.         controlTag[0] = kTXNWordWrapStateTag;
  704.         GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  705.         status = TXNGetTXNObjectControls(object, 1, controlTag, controlData);
  706.  
  707.         if (controlData[0].uValue == kTXNAutoWrap)         // if we are autowrapped
  708.         {
  709.             controlData[0].uValue = kTXNNoAutoWrap;     // toggle to not autowrapped
  710.             CheckItem(layoutMenu, iAutoWrap, false);    // uncheck this menu item
  711.         }
  712.         else
  713.         {
  714.             controlData[0].uValue = kTXNAutoWrap;
  715.             CheckItem(layoutMenu, iAutoWrap, true);    // check this menu item
  716.         }
  717.         status = TXNSetTXNObjectControls(object, false, 1, controlTag, controlData);
  718.         
  719.         if (status != noErr)
  720.             AlertUser(eNoWordWrap);
  721.     }
  722. }
  723.  
  724. // Create a new document and window.
  725. void DoNew(void)
  726. {
  727.     WindowPtr        window;
  728.     MenuHandle         layoutMenu;
  729.     OSStatus        status = noErr;
  730.     
  731.     window = GetNewCWindow(rDocWindow, NULL, (WindowPtr)-1L);
  732.     
  733.     if (window != NULL) 
  734.     {
  735.         // Step 3 -- create a new TXNObject.
  736.         TXNObject        object = NULL;
  737.         TXNFrameID        frameID    = 0;
  738.         Rect            *framePtr = &window->portRect;
  739.         TXNFrameOptions    frameOptions = kTXNWantHScrollBarMask | kTXNWantVScrollBarMask 
  740.                                         | kTXNDrawGrowIconMask | kTXNShowWindowMask |kTXNNoKeyboardSyncMask;
  741.  
  742.         status = TXNNewObject(    NULL,         // start with an empty document
  743.                                 window, 
  744.                                 framePtr,    // the area to fill
  745.                                 frameOptions,
  746.                                 kTXNTextEditStyleFrameType,
  747.                                 kTXNTextensionFile,
  748.                                 kTXNSystemDefaultEncoding,
  749.                                 &object,    // ptr to opaque TXNObject
  750.                                 &frameID,     // always 0 in ver 1.0
  751.                                 0);
  752.         if (status == noErr)
  753.         {        
  754.             // Step 4 -- store a reference to the oject and the frameID
  755.             SetWindowProperty(window,'GRIT','tFrm',sizeof(TXNFrameID),&frameID);
  756.             SetWindowProperty(window,'GRIT','tObj',sizeof(TXNObject),&object);        
  757.             AdjustMenus();
  758.             gNumDocuments++;            // will be decremented in DoCloseWindow            
  759.             DoJustification(window, iDefaultJustify);     // set justification default for new doc
  760.             layoutMenu = GetMenuHandle(mLayout);
  761.             CheckItem(layoutMenu, iAutoWrap, true);        // check this menu item
  762.             // ShowWindow(window);
  763.         }
  764.         else
  765.         {
  766.             CloseWindow(window);
  767.             window = NULL;
  768.             AlertUser(eNoWindow);    // TXNNewObject failed -  tell user
  769.         }
  770.     }
  771.     else
  772.         AlertUser(eNoWindow);        // window was null - tell user
  773. }
  774.  
  775. // Close a window. Handles desk accessory and application windows.
  776. Boolean DoCloseWindow(WindowPtr window)
  777. {
  778.     TXNObject    object = NULL;
  779.     Boolean     isClosed = true;
  780.  
  781.     if (IsDAWindow(window))
  782.     {
  783.         CloseDeskAcc(GetWindowKind(window));
  784.     }
  785.     else if (IsAppWindow(window))
  786.     {
  787.  
  788.         if (isClosed) 
  789.         {
  790.             // Step 5 -- delete the TXNObject.
  791.             GetWindowProperty(window, 'GRIT', 'tObj', sizeof(TXNObject), NULL, &object);
  792.             TXNDeleteObject(object);
  793.             
  794.             CloseWindow(window);
  795.             DisposePtr((Ptr) window);
  796.             gNumDocuments -= 1;
  797.         }
  798.     }
  799.     AdjustMenus();
  800.     return isClosed;
  801. }
  802.  
  803. // Clean up and exit. Close all of the windows.
  804. void Terminate()
  805. {
  806.     WindowPtr    aWindow;
  807.     Boolean        closed;
  808.     OSStatus    status = noErr;
  809.     
  810.     closed = true;
  811.     do {
  812.         aWindow = FrontWindow();                // get current front window
  813.         if (aWindow != NULL)
  814.             closed = DoCloseWindow(aWindow);    // close this window
  815.     }
  816.     while (closed && (aWindow != NULL));
  817.  
  818.     if (closed)
  819.     {
  820.         // Step 28 -- dispose font menu object before terminating Textension.
  821.         if (gTXNFontMenuObject != NULL) 
  822.         {
  823.             status = TXNDisposeFontMenuObject(gTXNFontMenuObject);
  824.             if (status != noErr)
  825.                 AlertUser(eNoDisposeFontMenuObject);
  826.             gTXNFontMenuObject = NULL;  //    Nullify font menu object.
  827.         }
  828.  
  829.         // Step 2 -- Terminate MLTE
  830.         TXNTerminateTextension();
  831.         ExitToShell();
  832.     }
  833. }
  834.  
  835. // Check whether a window is a document window created by the application.
  836. // These windows are distinguished from desk accessories, dialogs, and  
  837. // other windows by their windowKind userKind.
  838. Boolean IsAppWindow(WindowPtr window)
  839. {
  840.     OSErr status = noErr;
  841.     
  842.     return (window != NULL) && (((WindowPeek) window)->windowKind == userKind);
  843. }
  844.  
  845. // Check to see if a window belongs to a desk accessory.
  846. Boolean IsDAWindow(WindowPtr window)
  847. {
  848.     if (window == NULL)
  849.         return false;
  850.     else    // DA windows have negative windowKinds
  851.         return ((WindowPeek) window)->windowKind < 0;
  852. }
  853.  
  854. //    Display an alert that tells the user an error occurred.
  855. void AlertUser(short error)
  856. {
  857.     short        itemHit;
  858.     Str255        message;
  859.  
  860.     SetCursor(&qd.arrow);
  861.     GetIndString(message, kErrStrings, error);
  862.     ParamText(message, (ConstStr255Param)"",(ConstStr255Param)"", (ConstStr255Param)"");
  863.     itemHit = Alert(rUserAlert, NULL);
  864. }
  865.  
  866. // Used whenever a fatal error happens
  867. void BigBadError(short error)
  868. {
  869.     AlertUser(error);
  870.     ExitToShell();
  871. }
  872.  
  873. // install the core apple event handlers
  874. void InstallAppleEventHandlers(void)
  875. {
  876.     long result;
  877.     
  878.     OSErr err = Gestalt(gestaltAppleEventsAttr, &result);
  879.     
  880.     if (err == noErr)
  881.     {    // we should check the AEInstallEventHandler return value but since it's just a sample...
  882.         AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, NewAEEventHandlerProc(HandleOapp), 0, false);
  883.         AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,   NewAEEventHandlerProc(HandleOdoc), 0, false);
  884.         AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,  NewAEEventHandlerProc(HandlePdoc), 0, false);
  885.         AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(HandleQuit), 0, false);
  886.     }
  887. }
  888.  
  889. // Respond to an open application apple event
  890. pascal OSErr HandleOapp (const AppleEvent *aevt, AEDescList *reply, UInt32 refCon)
  891. {
  892. #pragma unused (aevt, reply, refCon)
  893.     return noErr;
  894. }
  895.  
  896. // Respond to an open document apple event
  897. pascal OSErr HandleOdoc (const AppleEvent *aevt, AEDescList *reply, UInt32 refCon)
  898. {
  899. #pragma unused (aevt, reply, refCon)
  900.     return errAEEventNotHandled;
  901. }
  902.  
  903. // Respond to a print apple event
  904. pascal OSErr HandlePdoc (const AppleEvent *aevt, AEDescList *reply, UInt32 refCon)
  905. {
  906. #pragma unused (aevt, reply, refCon)
  907.     return errAEEventNotHandled;
  908. }
  909.  
  910. // Respond to a quit apple event
  911. pascal OSErr HandleQuit (const AppleEvent *aevt, AEDescList *reply, UInt32 refCon)
  912. {
  913. #pragma unused (aevt, reply, refCon)
  914.     Terminate();
  915.     return noErr;
  916. }